home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_11 / 1011024a < prev    next >
Text File  |  1992-09-07  |  4KB  |  172 lines

  1.  
  2. /* MSM.c, Copyright (C) 1992 by Jon Shemitz.
  3.  
  4.    A MSM engine and not much else -- this code
  5.    has been slashed to minimize magazine space:
  6.    Features and *error checking* have been
  7.    stripped out and made "exercises for the reader".
  8. */
  9.  
  10. #include "msm.h"
  11.  
  12. // The TaskList is privately declared. Encapsulation
  13. // the "old fashioned" way.
  14.  
  15. enum OnOff {On, Off};
  16.  
  17. struct TaskList {
  18.        Byte      Length;
  19.        TaskToken List[NTasks];
  20.  
  21.        TaskList()               {Length = 0;}
  22.        void Append(TaskToken T) {List[Length++] = T;}
  23.        void Delete(TaskToken T);
  24.        int ContainsP(TaskToken T)
  25.          {return IndexOf(T) < Length;}
  26.  
  27.        private:
  28.          int IndexOf(TaskToken T);
  29.      // Returns Length iff not found
  30.        };
  31. typedef TaskList* PTaskList;
  32.  
  33. void TaskList::Delete(TaskToken T)
  34. {
  35.   int Index = IndexOf(T);
  36.   if (Index < Length) Length--;
  37.   for ( ; Index < Length; Index++)
  38.     List[Index] = List[Index+1];
  39. };
  40.  
  41. int TaskList::IndexOf(TaskToken T)
  42. {
  43.   int Index;
  44.   for (Index = 0;
  45.        Index < Length && List[Index] != T;
  46.        Index++) ;
  47.   return Index;
  48. };
  49.  
  50. struct MSM {
  51.        OnOff      Tasking;
  52.        TaskPtr      Ptr[NTasks];
  53.        TaskList      Foreground;
  54.        TaskList   Background;
  55.  
  56.        MSM(); // Guarantee initialization
  57.        } Taskz;
  58.  
  59. // Tasks' member functions
  60.  
  61. Tasks::Tasks(Handler S, Word W, Priorities P)
  62. {
  63.   State    = S;    // Starting state
  64.   Waits    = W; // Starting waitmap
  65.   Priority = P; // Starting priority
  66.  
  67.   TaskToken N; // Find 1st TaskToken
  68.   for (N = 0; Taskz.Ptr[N] != 0; N++) ;
  69.   Number       = N;    // Point task to slot
  70.   Taskz.Ptr[N] = this; // Point slot to task
  71.  
  72.   if (W == 0) Activate(); // Add to active task list(s)
  73. };
  74.  
  75. Tasks::~Tasks()
  76. {
  77.   if (Waits == 0) Deactivate();
  78.   // Remove from active task lists
  79.   Taskz.Ptr[Number] = 0;
  80.   // Clear the task slot
  81. };
  82.  
  83. void Tasks::SetPriority(Priorities P)
  84. {
  85.   int Moved = ((Priority == 0) != (P == 0)) &&
  86.             (Waits == 0);
  87.   // Has the task moved from Foreground to Background
  88.   // or vice versa?
  89.   if (Moved) Deactivate(); // Remove from current list
  90.   Priority = P;            // Set new priority
  91.   if (Moved) Activate();   // Place on new list
  92. };
  93.  
  94. void Tasks::Activate()
  95. {
  96.   PTaskList List = (Priority == 0)  ?
  97.                    & Taskz.Background :
  98.            & Taskz.Foreground ;
  99.   if (!List->ContainsP(Number)) // If not in list
  100.     List->Append(Number);       // then add it
  101. };
  102.  
  103. void Tasks::Deactivate()
  104. {
  105.   PTaskList List = (Priority == 0)  ?
  106.              & Taskz.Background :
  107.            & Taskz.Foreground ;
  108.   List->Delete(Number); // Delete it iff present
  109. };
  110.  
  111. // MSM 'engine' code
  112.  
  113. TaskPtr ThisTask = 0;
  114.  
  115. MSM::MSM() // Initialize MSM 'engine'
  116. {
  117.   for (TaskToken Idx = 0;
  118.        Idx < NTasks;
  119.        Taskz.Ptr[Idx++] = 0) ;
  120.   // Clear all slots
  121. };
  122.  
  123. void MSM_Run() // Run the 'engine'
  124. {
  125.   Taskz.Tasking = On;
  126.   while (Taskz.Tasking == On)
  127.     if (Taskz.Foreground.Length != 0) {
  128.       // Run foreground tasks
  129.       Priorities Level;
  130.       int        Idx, NextLevel;
  131.  
  132.  
  133.       for (NextLevel = 1, Level = 1;
  134.            NextLevel;
  135.        Level++) {
  136.     NextLevel = 0; // No GetPriority() > Level yet
  137.         for (Idx = Taskz.Foreground.Length - 1;
  138.          Idx >= 0; Idx--) {
  139.           // Execute most-recently-awoken tasks first
  140.           ThisTask =
  141.         Taskz.Ptr[Taskz.Foreground.List[Idx]];
  142.           if (ThisTask->GetPriority() >= Level)
  143.         (*ThisTask->GetState())();
  144.             // Execute state handler
  145.           NextLevel = NextLevel ||
  146.                   ThisTask->GetPriority() > Level;
  147.           // NextLevel == 1 as soon any Priority>Level
  148.           };
  149.         };
  150.       } else {
  151.       // Run background tasks
  152.       int Idx = Taskz.Background.Length - 1;
  153.       while (Idx >= 0) {
  154.         ThisTask =
  155.       Taskz.Ptr[Taskz.Background.List[Idx--]];
  156.         (*ThisTask->GetState())(); // Execute handler
  157.         };
  158.       };
  159. };
  160.  
  161. void MSM_Stop() // Handlers can call to stop the engine
  162. {
  163.   Taskz.Tasking = Off;
  164. };
  165.  
  166. TaskPtr Task(TaskToken TT)
  167. {
  168.   return Taskz.Ptr[TT];
  169. }
  170. WRAP_EOF
  171.  
  172.